package data

import (
	"context"
	"github.com/go-kratos/kratos/contrib/registry/consul/v2"
	"github.com/go-kratos/kratos/v2/middleware/recovery"
	"github.com/go-kratos/kratos/v2/registry"
	"github.com/go-kratos/kratos/v2/transport/grpc"
	"github.com/google/wire"
	consulAPI "github.com/hashicorp/consul/api"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/sdk/trace"
	g_grpc "google.golang.org/grpc"
	orderV1 "shop-demo/api/order/v1"
	productV1 "shop-demo/api/product/v1"
	userV1 "shop-demo/api/user/v1"
	"shop-demo/app/shop/admin/internal/conf"
)

type Data struct {
	userClient    userV1.UserClient
	orderClient   orderV1.OrderClient
	productClient productV1.ProductClient
}

var ProviderSet = wire.NewSet(NewData, NewDiscovery, NewOrderRepo, NewUserRepo, NewProductRepo, NewUserServiceClient, NewOrderServiceClient, NewProductServiceClient)

func NewData(userClient userV1.UserClient, orderClient orderV1.OrderClient, productClient productV1.ProductClient) *Data {
	return &Data{
		userClient:    userClient,
		orderClient:   orderClient,
		productClient: productClient,
	}
}

func NewDiscovery(regConf *conf.Registry) registry.Discovery {
	c := consulAPI.DefaultConfig()
	c.Address = regConf.Consul.Addr
	c.Scheme = regConf.Consul.Scheme
	client, err := consulAPI.NewClient(c)
	if err != nil {
		panic(err)
	}
	r := consul.New(client, consul.WithHealthCheck(false))
	return r
}

func NewConn(discovery registry.Discovery, endpoint string) *g_grpc.ClientConn {
	conn, err := grpc.DialInsecure(
		context.Background(),
		grpc.WithEndpoint(endpoint),
		grpc.WithDiscovery(discovery),
		grpc.WithMiddleware(
			recovery.Recovery(),
		),
	)
	if err != nil {
		panic(err)
	}
	return conn
}

func NewUserServiceClient(discovery registry.Discovery, tp *trace.TracerProvider) userV1.UserClient {
	otel.SetTracerProvider(tp)
	conn := NewConn(discovery, "discovery:///shop.user.service")
	return userV1.NewUserClient(conn)
}

func NewOrderServiceClient(discovery registry.Discovery, tp *trace.TracerProvider) orderV1.OrderClient {
	otel.SetTracerProvider(tp)
	conn := NewConn(discovery, "discovery:///shop.order.service")
	return orderV1.NewOrderClient(conn)
}

func NewProductServiceClient(discovery registry.Discovery, tp *trace.TracerProvider) productV1.ProductClient {
	otel.SetTracerProvider(tp)
	conn := NewConn(discovery, "discovery:///shop.product.service")
	return productV1.NewProductClient(conn)
}
